import asyncio
import logging
from typing import Dict, Callable
from datetime import datetime
try:
    from asyncua import Client, ua
    ASYNCUA_AVAILABLE = True
except ImportError:
    ASYNCUA_AVAILABLE = False
    logging.warning("asyncua library not installed. OPC UA functionality will be disabled.")

class OpcUaMonitor:
    def __init__(self, db_manager):
        self.db_manager = db_manager
        self.monitoring_active = True
        self.connection_status_callback: Callable[[int, str], None] = None
        # 扫描间隔（秒）
        self.scan_interval = 10
        
    def set_status_callback(self, callback: Callable[[int, str], None]):
        """设置连接状态更新回调函数"""
        self.connection_status_callback = callback
    
    def set_scan_interval(self, interval: int):
        """设置扫描间隔（秒）"""
        if 1 <= interval <= 3600:
            self.scan_interval = interval
    
    async def check_connection(self, url: str, node_id: str) -> str:
        """检查OPC UA连接状态"""
        if not ASYNCUA_AVAILABLE:
            logging.info("asyncua library not available")
            return "unavailable"
            
        try:
            logging.info(f"Attempting to connect to {url} with node {node_id}")
            async with Client(url=url, timeout=5) as client:
                # 尝试读取节点值以确认连接
                node = client.get_node(node_id)
                value = await node.read_value()
                logging.info(f"Successfully connected to {url}, node value: {value}")
                return "connected"
        except Exception as e:
            logging.error(f"Connection failed for {url} node {node_id}: {str(e)}")
            return "disconnected"
    
    async def monitor_single_point(self, point_id: int, url: str, node_id: str, enabled: int):
        """监控单个OPC UA点位"""
        if not enabled or not self.monitoring_active:
            return
            
        status = await self.check_connection(url, node_id)
        
        # 调用回调函数通知状态更新（仅更新前端显示，不存入数据库）
        if self.connection_status_callback:
            self.connection_status_callback(point_id, status)
    
    async def monitor_all_points(self):
        """监控所有OPC UA点位"""
        while self.monitoring_active:
            points = self.db_manager.get_all_points()
            tasks = []
            
            for point in points:
                # 根据数据库表结构，字段顺序是：
                # 0:id, 1:name, 2:url, 3:node_id, 4:enabled
                point_id, name, url, node_id, enabled = point
                task = self.monitor_single_point(point_id, url, node_id, enabled)
                tasks.append(task)
                
            if tasks:
                await asyncio.gather(*tasks, return_exceptions=True)
            
            # 根据设置的扫描间隔等待
            await asyncio.sleep(self.scan_interval)
    
    def start_monitoring(self):
        """开始监控"""
        self.monitoring_active = True
    
    def stop_monitoring(self):
        """停止监控"""
        self.monitoring_active = False